package com.zfast.yugioh.junit;

import cn.hutool.core.util.ObjectUtil;
import com.zfast.yugioh.antlr4.effect.EffectLexer;
import com.zfast.yugioh.antlr4.effect.EffectParser;
import com.zfast.yugioh.antlr4.effect.impl.EffectBaseListenerImpl;
import com.zfast.yugioh.antlr4.effect.impl.EffectBaseVisitorImpl;
import com.zfast.yugioh.bo.*;
import com.zfast.yugioh.constant.DefineEnum;
import lombok.SneakyThrows;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @author zgn
 * @Description: simJunit
 * @date 2022/1/13 0013
 */
public class yugiohJunit {
    Random r=new Random();
    GameBo gameBo=new GameBo();
    //相对路径 eg.1(实体机): D:\IDEAWork\play\private\yu-gi-oh
    String relativelyPath = System.getProperty("user.dir");
    @Test
    public void egMax() {//e.g.
        //region 1.模拟数据
        System.out.println("--------------------Start--------------------");
        //endregion

        //region 2.数据处理
        System.out.println("--------------------Deal--------------------");
        //endregion

        //region 3.数据展示
        System.out.println("--------------------Done--------------------");
        //endregion
    }

    @Test
    public void 随机数_egMin() {//e.g.
        for(int i=0;i<5;i++){
            System.out.println(r.nextInt(4)+1);
        }
    }

    @Test
    public void DefineEnum_常量_egMin() {//e.g.
        System.out.println(DefineEnum.health.getValue());
    }

    @Test
    public void 余数_egMin() {//e.g.
        int startNum=3;
        System.out.println(startNum%2);
    }

    @Test
    public void 字串分割_egMin() {//e.g.
        String str="吼!;";
        String[] split = str.split(";");
        for (int i = 0; i < split.length; i++) {
            String s = split[i];
            System.out.println(i+":"+s);
        }

    }

    @Test
    public void 对象复制_egMin() {//e.g.
        List<CardBo> handCards=new ArrayList<>();
        CardBo test001=CardBo.builder().name("test001").build();
        handCards.add(test001);
        GameDetailBo player1=GameDetailBo.builder()
                .health(6000).handCards(handCards)
                .build();
        //GameDetailBo player2=new GameDetailBo();//人机2号
        //org.springframework.beans.BeanUtils.copyProperties(player1, player2);
        //GameDetailBo player2 = ObjectUtil.cloneByStream(player1);
        GameDetailBo player2 = ObjectUtil.clone(player1);
        //基本数据类型
        player1.setHealth(5);
        //System.out.println(player2.getHealth());

        //对象
        test001.setName("test002");
        System.out.println(player1.getHandCards().get(0).getName());
        System.out.println(player2.getHandCards().get(0).getName());
    }

    @Test
    public void 变更引用实体类中参数_egMin() {//e.g.

        List<CardBo> handCards=new ArrayList<>();
        CardBo test001=CardBo.builder().name("test001").build();
        handCards.add(test001);
        GameDetailBo player1=GameDetailBo.builder()
                .health(6000).handCards(handCards)
                .build();

        变更实体类中参数_egMin(test001,player1);

        System.out.println();
    }

    public void 变更实体类中参数_egMin(CardBo test001,GameDetailBo player1) {//e.g.
        test001.setName("test002");
        System.out.println(player1.getHandCards().get(0).getName());
    }

    @Test
    public void 等待输入_egMin() {//e.g.
        System.out.println("等待输入_egMin");
        Scanner input = new Scanner(System.in);
        String val = null;       // 记录输入度的字符串
        do{
            System.out.print("请输入：");
            val = input.next();       // 等待输入值
            System.out.println("您输入的是："+val);
        }while(!val.equals("#"));   // 如果输入的值不版是#就继续输入
            System.out.println("你输入了\"#\"，程序已经退出！");
        input.close(); // 关闭资源
    }

    @Test
    public void 相对路径_egMin() {//e.g.
        String relativelyPath = System.getProperty("user.dir");//D:\IDEAWork\play\private\yu-gi-oh
        //D:\IDEAWork\play\private\yu-gi-oh\src\test\java\com\zfast\yugioh\junit\antlr4\rec\g4.txt
        System.out.println(relativelyPath+ File.separator+"src"+File.separator+"test"+File.separator+"java"+File.separator+"com"+File.separator+"zfast"+File.separator+"yugioh"+File.separator+"junit"+File.separator+"antlr4"+File.separator+"rec"+File.separator+"g4.txt");
        System.out.println(relativelyPath+"\\src\\test\\java\\com\\zfast\\yugioh\\junit\\antlr4\\rec\\g4.txt");
    }

    @SneakyThrows
    @Test
    public void antlr4_EffcetListen_语法解析_egMin() {//e.g.
        initGame();
        //树对象 gameDetailBoPlayOne.cards.size √
        //字串 "phase"
        //数值 123
        //String parserStr="gameDetailBoPlayOne.cards.size";
        //2022年7月22日
        //对象内:IsTrue;size;dialogue
        //gameBo:turn;gameDetailBoPlayOne.handCards.size
        String parserStr="size";
        CharStream inputStream = CharStreams.fromFileName(relativelyPath+"\\src\\test\\java\\com\\zfast\\yugioh\\junit\\antlr4\\rec\\g4.txt", Charset.forName("UTF-8"));
        EffectLexer lexer = new EffectLexer(inputStream);

        //EffectLexer lexer = new EffectLexer(CharStreams.fromString("SELECT IsTrue SET asd FROM gameDetailBoMe TO asdas WHERE whererere LIMIT limisada"));
        CommonTokenStream token = new CommonTokenStream(lexer);
        EffectParser parser = new EffectParser(token);

        //ParseTree tree =parser.exprExt1();
        //System.out.println(tree.toStringTree());
        ParseTreeWalker walker= new ParseTreeWalker();
        EffectBaseListenerImpl effectBaseListener = new EffectBaseListenerImpl(parser);
        effectBaseListener.setGameBo(gameBo);
        //首发玩家的手卡
        List<CardBo> handCards = gameBo.getGameDetailBoPlayOne().getHandCards();
        CardBo 发动卡 = handCards.get(handCards.size() - 1);
        effectBaseListener.getEffectBo().setCardBo(发动卡);

        //List<Integer> integers = effectBaseListener.ParserTransformBo(parserStr, Integer.class);
        //System.out.println(integers.get(0));
        //2022年7月19日 语法对象
        //List<BigDecimal> integers = effectBaseListener.ParserTransformBo(parserStr, BigDecimal.class);
        //System.out.println(integers.get(0));

        //2022年7月20日 解析
        //walker.walk(effectBaseListener,tree);
        //EffectBo effectBo = effectBaseListener.getEffectBo();

        /*System.out.println("--------------------显示limitStr的解析结果--------------------");
        System.out.println(effectBo.getLimitStr());
        System.out.println(effectBo.getLimitStart());
        System.out.println(effectBo.getLimitNum());*/

        //2022年8月4日
        /*System.out.println("--------------------简易set动作测试_step2--------------------");
        List<CardBo> play1_handCards = gameBo.getGameDetailBoPlayOne().getHandCards();
        for (int i = 0; i < play1_handCards.size(); i++) {
            CardBo cardBo =  play1_handCards.get(i);
            System.out.println(cardBo.getName());
        }*/

        //2022年7月22日 字串对象优先级 Integer;String
        //System.out.println(effectBaseListener.ParserTransformBo(parserStr, Integer.class,false));

        //2022年8月4日 test_TO_001
        /*System.out.println("--------------------TO 表达式测试语句_转到墓地卡--------------------");

        List<CardBo> play1_graveyardCards = gameBo.getGameDetailBoPlayOne().getGraveyardCards();
        for (int i = 0; i < play1_graveyardCards.size(); i++) {
            CardBo cardBo =  play1_graveyardCards.get(i);
            System.out.println("[名称]:" + cardBo.getName() + "\n"
                    + "[特性效果]:" + cardBo.getEffectsFeatures() + "\n"
                    + "[登场次数]:" + cardBo.getNum() + "\n");
        }*/

        //2022年8月15日
        System.out.println("--------------------自定义处理语句--------------------");
        EffectParser.ExprExt1Context exprExt1Context = parser.exprExt1();
        effectBaseListener.doOrgExpressionParse(exprExt1Context);

        //2022年8月16日
        /*System.out.println("--------------------ThisCardBo+SummonType--------------------");
        System.out.println(发动卡.getExpandMap());*/
        //2022年8月12日
        /*System.out.println("--------------------test_AS_003 AS 表达式测试语句--------------------");
        HashMap expandMap = effectBaseListener.getExpandMap();
        System.out.println(expandMap);*/

        //2022年8月5日
        System.out.println("--------------------强欲之壶 真实效果测试--------------------");

        List<CardBo> play1_handCards = gameBo.getGameDetailBoPlayOne().getHandCards();
        for (int i = 0; i < play1_handCards.size(); i++) {
            CardBo cardBo =  play1_handCards.get(i);
            System.out.println("[名称]:" + cardBo.getName() + "\n"
                    + "[特性效果]:" + cardBo.getEffectsFeatures() + "\n"
                    + "[登场次数]:" + cardBo.getNum() + "\n");
        }
    }

    @SneakyThrows
    @Test
    public void antlr4_EffcetVisitor_语法解析_egMin() {//e.g.
        initGame();

        CharStream inputStream = CharStreams.fromFileName(relativelyPath+"\\src\\test\\java\\com\\zfast\\yugioh\\junit\\antlr4\\rec\\g4.txt", Charset.forName("UTF-8"));
        EffectLexer lexer = new EffectLexer(inputStream);

        CommonTokenStream token = new CommonTokenStream(lexer);
        EffectParser parser = new EffectParser(token);

        EffectBaseListenerImpl effectBaseListener = new EffectBaseListenerImpl(parser);
        effectBaseListener.setGameBo(gameBo);

        EffectBaseVisitorImpl effectBaseVisitor=new EffectBaseVisitorImpl();
        //orgExpression
        //effectBaseVisitor.visitOrgExpression(parser.orgExpression());

        //只在limitStr 中进行
        /*EffectParser.LimitStrContext limitStrContext = parser.limitStr();
        System.out.println();*/

        //effectBaseVisitor.visitLimit();
        EffectParser.OrgExpressionContext ruleContext = parser.exprExt1().getRuleContext(EffectParser.OrgExpressionContext.class, 0);
        effectBaseVisitor.visitOrgExpression(ruleContext);
    }

    @Test
    public void 字串点号分割_egMin() {//e.g.
        String parser="gameDetailBoPlayOne.cards.size";
        boolean contains = parser.contains(".");
        System.out.println(contains);
        String[] split = parser.split("\\.");
        for (int i = 0; i < split.length; i++) {
            String s = split[i];
            System.out.println(s);
        }

    }

    //初始化游戏进程
    public CardBo initCard(){
        CardBo cardBo=CardBo.builder()
                .name("电子龙")
                .build();
        return cardBo;
    }
    //初始化对局信息
    public void initGame(){
        int phase = 5,//阶段
                turn = 1//回合
                        ;
        gameBo.setPhase(phase);
        gameBo.setTurn(turn);
        initPlay1();
        initPlay2();
    }
    public GameBo initPlay1(){
        //region 可调节复用参数信息
        int handCardsNum=5,//手卡数
                liveCardsNum=3,//场上卡牌数
                cardsNum=20;//卡组数量

        String play_unique = "Play1_",
                effectsFeatures = play_unique + "特性效果",//特性效果
                card_code = play_unique + "cards",
                handCards_code = play_unique + "handCards",
                liveCards_code = play_unique + "liveCards",
                dialogue = play_unique + "测试对话",

                //expandMap key_value
                expandMap_key_AAA = "AAA",
                expandMap_value_AAA = "789",
                expandMap_key_IsTrue = "IsTrue",
                expandMap_value_IsTrue = "3";
        //endregion

        //region 卡组
        //region cards
        List<CardBo> cards=new ArrayList<>();
        for (int i = 0; i < cardsNum; i++) {
            CardBo cardBo=CardBo.builder()
                    .name(card_code+i)
                    .effectsFeatures(effectsFeatures)
                    .build();
            /*CardBo cardBo=CardBo.builder()
                    .name("同名cards"+i)
                    .effectsFeatures(effectsFeatures)
                    .build();*/
            cards.add(cardBo);
        }
        //endregion
        //region handCards
        List<CardBo> handCards=new ArrayList<>();
        for (int i = 0; i < handCardsNum; i++) {
            CardBo cardBo=CardBo.builder()
                    .name(handCards_code+i)
                    .effectsFeatures(effectsFeatures)
                    .build();
            /*CardBo cardBo=CardBo.builder()
                    .name("同名cards"+i)
                    .effectsFeatures(effectsFeatures)
                    .build();*/
            handCards.add(cardBo);
        }

        CardBo 发动卡 = initCard();
        handCards.add(发动卡);


        //endregion
        //region liveCards
        List<CardBo> liveCards=new ArrayList<>();
        for (int i = 0; i < liveCardsNum; i++) {
            CardBo cardBo=CardBo.builder()
                    .name(liveCards_code+i)
                    .kind(0)
                    .effectsFeatures(effectsFeatures)
                    .build();
            /*CardBo cardBo=CardBo.builder()
                    .name("同名cards"+i)
                    .effectsFeatures(effectsFeatures)
                    .build();*/
            liveCards.add(cardBo);
        }
        //endregion
        //region graveyardCards 暂无
        //endregion
        //endregion

        //region 拓展记录
        HashMap expandMap = new HashMap();
        expandMap.put(expandMap_key_AAA,expandMap_value_AAA);
        expandMap.put(expandMap_key_IsTrue,expandMap_value_IsTrue);
        //endregion

        //region 玩家个人信息
        UserBo userBo= UserBo.builder()
                .expandMap(expandMap)
                .dialogue(dialogue)
                .build();
        //endregion

        //region 先手玩家对局信息
        GameDetailBo gameDetailBoPlayOne=GameDetailBo.builder()
                .cards(cards)
                .handCards(handCards)
                .liveCards(liveCards)
                .userBo(userBo)
                .expandMap(expandMap)
                .build();
        //endregion

        //region 对局
        gameBo.setGameDetailBoPlayOne(gameDetailBoPlayOne);
        //endregion

        return gameBo;
    }

    public GameBo initPlay2(){
        //region 可调节复用参数信息
        int handCardsNum=3,//手卡数
                liveCardsNum=5,//场上卡牌数
                cardsNum=40;//卡组数量

        String play_unique = "Play2_",
                effectsFeatures = play_unique + "特性效果",//特性效果
                card_code = play_unique + "cards",
                handCards_code = play_unique + "handCards",
                liveCards_code = play_unique + "liveCards",
                dialogue = play_unique + "测试对话",

                //expandMap key_value
                expandMap_key_AAA = "AAA",
                expandMap_value_AAA = "789",
                expandMap_key_IsTrue = "IsTrue",
                expandMap_value_IsTrue = "3";
        //endregion

        //region 卡组
        //region cards
        List<CardBo> cards=new ArrayList<>();
        for (int i = 0; i < cardsNum; i++) {
            CardBo cardBo=CardBo.builder()
                    .name(card_code+i)
                    .effectsFeatures(effectsFeatures)
                    .build();
            /*CardBo cardBo=CardBo.builder()
                    .name("同名cards"+i)
                    .effectsFeatures(effectsFeatures)
                    .build();*/
            cards.add(cardBo);
        }
        //endregion
        //region handCards
        List<CardBo> handCards=new ArrayList<>();
        for (int i = 0; i < handCardsNum; i++) {
            CardBo cardBo=CardBo.builder()
                    .name(handCards_code+i)
                    .effectsFeatures(effectsFeatures)
                    .build();
            /*CardBo cardBo=CardBo.builder()
                    .name("同名cards"+i)
                    .effectsFeatures(effectsFeatures)
                    .build();*/
            handCards.add(cardBo);
        }
        //endregion
        //region liveCards
        List<CardBo> liveCards=new ArrayList<>();
        for (int i = 0; i < liveCardsNum; i++) {
            CardBo cardBo=CardBo.builder()
                    .name(liveCards_code+i)
                    .kind(0)
                    .effectsFeatures(effectsFeatures)
                    .build();
            /*CardBo cardBo=CardBo.builder()
                    .name("同名cards"+i)
                    .effectsFeatures(effectsFeatures)
                    .build();*/
            liveCards.add(cardBo);
        }
        //endregion
        //region graveyardCards 暂无
        //endregion
        //endregion

        //region 拓展记录
        HashMap expandMap = new HashMap();
        expandMap.put(expandMap_key_AAA,expandMap_value_AAA);
        expandMap.put(expandMap_key_IsTrue,expandMap_value_IsTrue);
        //endregion

        //region 玩家个人信息
        UserBo userBo= UserBo.builder()
                .expandMap(expandMap)
                .dialogue(dialogue)
                .build();
        //endregion

        //region 先手玩家对局信息
        GameDetailBo gameDetailBoPlayTwo=GameDetailBo.builder()
                .cards(cards)
                .handCards(handCards)
                .liveCards(liveCards)
                .userBo(userBo)
                .expandMap(expandMap)
                .build();
        //endregion

        //region 对局
        gameBo.setGameDetailBoPlayTwo(gameDetailBoPlayTwo);
        //gameBo.setExpandMap(expandMap);
        //gameBo.setPhase(5);
        //endregion

        return gameBo;
    }
    @Test
    public void int除法取整egMin() {//e.g.
        //Math.ceil(num)　　   取整位，再+1
        //Math.floor(num) 　　只保留整数位
        //Math.rint(num)　　   余数四舍五入
        double a=3,b=4;
        System.out.println(a/b);
        System.out.println(Math.ceil(a/b));
        System.out.println(Math.floor(a/b));
        System.out.println(Math.rint(a/b));
    }

    @SneakyThrows
    @Test
    public void 检测parser疑似会消耗token_egMin() {//e.g.
        CharStream inputStream = CharStreams.fromFileName(relativelyPath+"\\src\\test\\java\\com\\zfast\\yugioh\\junit\\antlr4\\rec\\g4.txt", Charset.forName("UTF-8"));
        EffectLexer lexer = new EffectLexer(inputStream);

        CommonTokenStream token = new CommonTokenStream(lexer);
        EffectParser parser = new EffectParser(token);
        EffectParser.ExprExt1Context exprExt1Context = parser.exprExt1();
        System.out.println("第一次读取");
        System.out.println(exprExt1Context.getText());

        EffectParser.ExprExt1Context exprExt1Context22 = parser.exprExt1();
        System.out.println("第2次读取");
        System.out.println(exprExt1Context22.getText());

    }

    @SneakyThrows
    @Test
    public void TransformByClass_egMin() {//e.g.
        CharStream inputStream = CharStreams.fromFileName(relativelyPath+"\\src\\test\\java\\com\\zfast\\yugioh\\junit\\antlr4\\rec\\g4.txt", Charset.forName("UTF-8"));
        EffectLexer lexer = new EffectLexer(inputStream);

        CommonTokenStream token = new CommonTokenStream(lexer);
        EffectParser parser = new EffectParser(token);

        EffectBaseListenerImpl effectBaseListener = new EffectBaseListenerImpl(parser);
        Integer integer = effectBaseListener.TransformByClass("998", Integer.class);
        System.out.println(integer);

        System.out.println(String.format("TransformByClass %n值:  %s " +
                "%n类:  %s ",integer, integer.getClass()));

    }

    @Test
    public void egMin() {//e.g.
        System.out.println();
    }
}
